package com.platform.modules.chat.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.platform.common.constant.AppConstants;
import com.platform.common.enums.YesOrNoEnum;
import com.platform.common.exception.BaseException;
import com.platform.common.shiro.ShiroUtils;
import com.platform.common.utils.SnowflakeUtils;
import com.platform.common.utils.redis.RedisUtils;
import com.platform.common.web.service.impl.BaseServiceImpl;
import com.platform.modules.chat.dao.ChatMsgDao;
import com.platform.modules.chat.domain.*;
import com.platform.modules.chat.enums.FriendTypeEnum;
import com.platform.modules.chat.enums.MsgStatusEnum;
import com.platform.modules.chat.service.*;
import com.platform.modules.chat.vo.*;
import com.platform.modules.push.enums.PushMsgTypeEnum;
import com.platform.modules.push.enums.PushTalkEnum;
import com.platform.modules.push.service.ChatPushService;
import com.platform.modules.push.vo.*;
import com.platform.modules.wallet.domain.WalletAccount;
import com.platform.modules.wallet.domain.WalletRedPacket;
import com.platform.modules.wallet.domain.WalletTransfer;
import com.platform.modules.wallet.service.WalletRedPacketService;
import com.platform.modules.wallet.service.WalletTransferService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 聊天消息 服务层实现
 * q3z3
 * </p>
 */
@Service("chatMsgService")
public class ChatMsgServiceImpl extends BaseServiceImpl<ChatMsg> implements ChatMsgService {

    @Resource
    private ChatMsgDao chatMsgDao;
    @Resource
    private ChatFriendService friendService;
    @Resource
    private ChatGroupService groupService;
    @Resource
    private ChatGroupInfoService groupInfoService;
    @Resource
    private ChatPushService chatPushService;
    @Resource
    private ChatUserService chatUserService;
    @Resource
    private ChatTalkService chatTalkService;
    @Resource
    private WalletTransferService walletTransferService;
    @Resource
    private WalletRedPacketService walletRedPacketService;
    @Resource
    private RedisUtils redisUtils;

    @Autowired
    public void setBaseDao() {
        super.setBaseDao(chatMsgDao);
    }

    @Override
    public List<ChatMsg> queryList(ChatMsg t) {
        List<ChatMsg> dataList = chatMsgDao.queryList(t);
        return dataList;
    }

    @Override
    public Integer clearRecord(String beforeToday) {
        return chatMsgDao.clearRecord(beforeToday);
    }

    @Transactional
    @Override
    public ChatVo03 sendFriendMsg(ChatVo01 chatVo) {
        Long userId = ShiroUtils.getUserId();
        Long friendId = chatVo.getUserId();
        PushMsgTypeEnum msgType = chatVo.getMsgType();
        ChatVo04 chatVo04 = null;
        // 系统好友
        PushParamVo paramVo = chatTalkService.talk(chatVo.getUserId(), chatVo.getContent());
        if (paramVo != null) {
            friendId = userId;
            msgType = PushMsgTypeEnum.TEXT;
        }
        // 自己给自己发消息
        else if (userId.equals(friendId)) {
            paramVo = ChatUser.initParam(chatUserService.getById(userId))
                    .setUserType(FriendTypeEnum.SELF)
                    .setContent(chatVo.getContent());
        }
        // 发送给好友的消息
        else {
            // 校验好友
            ChatFriend friend1 = friendService.getFriend(userId, friendId);
            if (friend1 == null) {
                return doResult(MsgStatusEnum.FRIEND_TO);
            }
            ChatFriend friend2 = friendService.getFriend(friendId, userId);
            if (friend2 == null) {
                return doResult(MsgStatusEnum.FRIEND_FROM);
            }
            if (YesOrNoEnum.YES.equals(friend1.getBlack())) {
                return doResult(MsgStatusEnum.FRIEND_BLACK);
            }
            if (YesOrNoEnum.YES.equals(friend2.getBlack())) {
                return doResult(MsgStatusEnum.FRIEND_BLACK);
            }
            ChatUser toUser = chatUserService.getById(friendId);
            if (toUser == null) {
                return doResult(MsgStatusEnum.FRIEND_DELETED);
            }
            paramVo = ChatUser.initParam(chatUserService.getById(userId))
//                    .setNickName(friend2.getRemark())
                    .setTop(friend2.getTop())
                    .setContent(chatVo.getContent());
            if (StrUtil.isNotBlank(friend2.getRemark())) {
                paramVo.setNickName(friend2.getRemark());
            }
            if (PushMsgTypeEnum.TRTC_VOICE_START.equals(msgType)
                    || PushMsgTypeEnum.TRTC_VIDEO_START.equals(msgType)) {
                chatVo04 = new ChatVo04()
                        .setUserId(friendId)
                        .setTrtcId(AppConstants.REDIS_TRTC_USER + friendId)
                        .setPortrait(toUser.getPortrait())
                        .setNickName(friend1.getRemark());
            } else if (PushMsgTypeEnum.TRANSFER.equals(msgType)) {
                JSONObject jsonObject = JSONUtil.parseObj(paramVo.getContent());
                if (StrUtil.isBlank(jsonObject.getStr("queryId"))) {
                    return doResult(MsgStatusEnum.QUERY_ID_NOT_EXIST);
                }
                WalletTransfer transfer = walletTransferService.transfer(chatVo, userId);
                jsonObject.set("transferId", String.valueOf(transfer.getId()));
                jsonObject.remove("payPassword");
//                jsonObject.set("inStatus", transfer.getInStatus().getCode());
//                jsonObject.set("click",0);
                paramVo.setContent(jsonObject.toString());
            } else if (PushMsgTypeEnum.RED_PACKET.equals(msgType)) {
                JSONObject jsonObject = JSONUtil.parseObj(paramVo.getContent());
                if (StrUtil.isBlank(jsonObject.getStr("queryId"))) {
                    return doResult(MsgStatusEnum.QUERY_ID_NOT_EXIST);
                }
                if (StrUtil.isBlank(jsonObject.getStr("type"))) {
                    return doResult(MsgStatusEnum.TYPE_NOT_EXIST);
                }
                WalletRedPacket transfer = walletRedPacketService.transfer(chatVo, userId);
                jsonObject.set("redPacketId", String.valueOf(transfer.getId()));
                jsonObject.remove("payPassword");
//                jsonObject.set("click",0);
                paramVo.setContent(jsonObject.toString());
            }
        }
        // 保存数据
        ChatMsg chatMsg = new ChatMsg()
                .setFromId(userId)
                .setToId(friendId)
                .setMsgType(msgType)
                .setTalkType(PushTalkEnum.SINGLE)
                .setContent(paramVo.getContent())
                .setCreateDate(DateUtil.date())
                .setCreateTime(DateUtil.date());
        this.add(chatMsg);
        // 推送
        chatPushService.pushMsg(paramVo.setToId(friendId).setMsgId(chatMsg.getId()), msgType);
        return doResult(MsgStatusEnum.NORMAL)
                .setMsgId(chatMsg.getId())
                .setUserInfo(chatVo04);
    }

    /**
     * 返回发送结果
     */
    private ChatVo03 doResult(MsgStatusEnum status) {
        return new ChatVo03().setStatus(status);
    }

    @Override
    public ChatVo03 sendGroupMsg(ChatVo02 chatVo) {
        String content = chatVo.getContent();
        Long fromId = ShiroUtils.getUserId();
        Long groupId = chatVo.getGroupId();
        // 查询群组
        ChatGroup group = groupService.getById(groupId);
        if (group == null) {
            return doResult(MsgStatusEnum.GROUP_NOT_EXIST);
        }

        if (group.getProhibit().equals(YesOrNoEnum.YES)) {
            try {
                groupService.verifyMaster(group, fromId);
            } catch (BaseException e) {
                return doResult(MsgStatusEnum.GROUP_PROHIBIT_YES);
            }
        }


        // 查询群明细
        ChatGroupInfo groupInfo = groupInfoService.getGroupInfo(groupId, fromId, YesOrNoEnum.NO);
        if (groupInfo == null || YesOrNoEnum.YES.equals(groupInfo.getKicked())) {
            return doResult(MsgStatusEnum.GROUP_INFO_NOT_EXIST);
        } else if (PushMsgTypeEnum.RED_PACKET.equals(chatVo.getMsgType())) {
            JSONObject jsonObject = JSONUtil.parseObj(content);
            if (StrUtil.isBlank(jsonObject.getStr("queryId"))) {
                return doResult(MsgStatusEnum.QUERY_ID_NOT_EXIST);
            }
            if (StrUtil.isBlank(jsonObject.getStr("type"))) {
                return doResult(MsgStatusEnum.TYPE_NOT_EXIST);
            }
            WalletRedPacket transfer = walletRedPacketService.transfer(chatVo, fromId);
            jsonObject.set("redPacketId", String.valueOf(transfer.getId()));
            jsonObject.remove("payPassword");
            content = jsonObject.toString();
        } else if (PushMsgTypeEnum.TRANSFER.equals(chatVo.getMsgType())) {
            JSONObject jsonObject = JSONUtil.parseObj(content);
            if (StrUtil.isBlank(jsonObject.getStr("queryId"))) {
                return doResult(MsgStatusEnum.QUERY_ID_NOT_EXIST);
            }
            WalletTransfer transfer = walletTransferService.transfer(chatVo, fromId);
            jsonObject.set("transferId", String.valueOf(transfer.getId()));

            ChatUser chatUser = chatUserService.getById(jsonObject.getLong("userId"));
            jsonObject.set("name", "向" + chatUser.getNickName() + "发起转账");
            jsonObject.remove("payPassword");
            content = jsonObject.toString();
        }
        // 保存数据
        ChatMsg chatMsg = new ChatMsg()
                .setFromId(fromId)
                .setToId(groupId)
                .setMsgType(chatVo.getMsgType())
                .setTalkType(PushTalkEnum.GROUP)
                .setContent(content)
                .setCreateDate(DateUtil.date())
                .setCreateTime(DateUtil.date());
        this.add(chatMsg);
        // 查询群列表
        List<PushParamVo> userList = groupService.queryFriendPushFrom(chatMsg);
        if (PushMsgTypeEnum.TRANSFER.equals(chatVo.getMsgType())) {//发送人和接收人可见
            JSONObject jsonObject = JSONUtil.parseObj(content);
            userList = userList.stream().filter(vo -> ObjectUtil.equals(vo.getToId(), jsonObject.getLong("userId")))
                    .collect(Collectors.toList());
        }
        // 群信息
        PushParamVo groupUser = new PushParamVo()
                .setUserId(group.getId())
                .setNickName(group.getName())
                .setPortrait(group.getPortrait());
        // 推送
        chatPushService.pushMsg(userList, groupUser, chatVo.getMsgType());
        return doResult(MsgStatusEnum.NORMAL)
                .setMsgId(chatMsg.getId());
    }

    @Override
    public PushBodyVo getBigMsg(String msgId) {
        String key = AppConstants.REDIS_MSG_BIG + msgId;
        if (!redisUtils.hasKey(key)) {
            return null;
        }
        String jsonStr = redisUtils.get(key);
        return JSONUtil.toBean(jsonStr, PushBodyVo.class);
    }

    @Override
    public List<ChatMsg> getMsgHistory(Long lasterId, Long toId) {
        return new ChatMsg().selectList(new LambdaQueryWrapper<ChatMsg>()
                .eq(ChatMsg::getToId, toId)
                .ge(ChatMsg::getId, lasterId));
    }

    @Override
    public List<ChatMsg> getMsgHistoryLaster(Long lasterId, Long toId) {

        LambdaQueryWrapper<ChatMsg> wrapper = new LambdaQueryWrapper<ChatMsg>()
                .eq(ChatMsg::getToId, toId)
                .ge(ChatMsg::getId, lasterId)
                .orderByDesc(ChatMsg::getId);

        IPage<ChatMsg> iPage = new Page(1, 1);//参数一是当前页，参数二是每页个数
        iPage = new ChatMsg().selectPage(iPage, wrapper);
        List<ChatMsg> records = iPage.getRecords();
        records.sort(Comparator.comparing(ChatMsg::getId));
        return records;
    }

    private int pageSize = 20;

    public List<PushBodyVo> getMsgUserRecord(Long fromId, Integer page) {

        Long toId = ShiroUtils.getUserId();

        ChatFriend friend = friendService.getFriend(toId, fromId);

        if (ObjectUtil.isNotEmpty(page)) {
            if (page <= 1) {
                page = 0;
            } else {
                page = (page - 1) * pageSize;
            }
        } else {
            page = 0;
        }

        List<MsgVo> msgVos = chatMsgDao.queryUserRecord(fromId, toId, page, pageSize);

        List<PushBodyVo> pushBodyVos = new ArrayList<>();
        for (MsgVo msgVo : msgVos) {
            PushBodyVo bodyVo = new PushBodyVo();
            bodyVo.setMsgId(String.valueOf(msgVo.getMsgId()));
            bodyVo.setPushType("MSG");
            bodyVo.setCreateTime(DateUtil.formatDateTime(msgVo.getCreateTime()));

            // 组装消息体
            PushMsgVo pushMsgVo = new PushMsgVo()
                    .setMsgType(msgVo.getMsgType())
                    .setContent(msgVo.getContent())
                    .setTop(friend.getTop().getCode());

            bodyVo.setMsgContent(pushMsgVo);

            PushFromVo fromVo = new PushFromVo()
                    .setUserId(String.valueOf(msgVo.getFromId()))
                    .setPortrait(msgVo.getPortrait())
                    .setNickName(msgVo.getNickName())
                    .setUserType(FriendTypeEnum.NORMAL.getCode());
            if (msgVo.getFromId().equals(fromId)) {
                if (StrUtil.isNotBlank(friend.getRemark())) {
                    fromVo.setNickName(friend.getRemark());
                }
            }

            bodyVo.setFromInfo(fromVo);

            pushBodyVos.add(bodyVo);
        }

        return pushBodyVos;
    }

    public List<PushBodyVo> getMsgGroupRecord(Long toId, Integer page) {

        if (ObjectUtil.isNotEmpty(page)) {
            if (page <= 1) {
                page = 0;
            } else {
                page = (page - 1) * pageSize;
            }
        } else {
            page = 0;
        }

        Long userId = ShiroUtils.getUserId();

        ChatGroup group = groupService.findById(toId);
        ChatGroupInfo groupInfo = groupInfoService.getGroupInfo(group.getId(), userId, YesOrNoEnum.YES);
        Set<Long> masterSet = groupService.getMasterSet(group);
        List<MsgVo> msgVos = chatMsgDao.queryGroupRecord(toId, page, pageSize);

        List<PushBodyVo> pushBodyVos = new ArrayList<>();
        for (MsgVo msgVo : msgVos) {
            PushBodyVo bodyVo = new PushBodyVo();
            bodyVo.setMsgId(String.valueOf(msgVo.getMsgId()));
            bodyVo.setPushType("MSG");
            bodyVo.setCreateTime(DateUtil.formatDateTime(msgVo.getCreateTime()));

            // 组装消息体
            PushMsgVo pushMsgVo = new PushMsgVo()
                    .setMsgType(msgVo.getMsgType())
                    .setContent(msgVo.getContent())
                    .setTop(groupInfo.getTop().getCode())
                    .setDisturb(groupInfo.getDisturb().getCode());

            bodyVo.setMsgContent(pushMsgVo);

            PushFromVo fromVo = new PushFromVo()
                    .setUserId(String.valueOf(msgVo.getFromId()))
                    .setPortrait(msgVo.getPortrait())
                    .setNickName(msgVo.getNickName())
                    .setUserType(FriendTypeEnum.NORMAL.getCode());

            if (group.getMaster().equals(msgVo.getFromId())) {
                fromVo.setLevel(1);
            } else if (masterSet.contains(msgVo.getFromId())) {
                fromVo.setLevel(2);
            } else {
                fromVo.setLevel(0);
            }

            if (!msgVo.getFromId().equals(userId)) {
                ChatFriend friend = friendService.getFriend(userId, msgVo.getFromId());
                if (ObjectUtil.isNotEmpty(friend)) {
                    if (StrUtil.isNotBlank(friend.getRemark())) {
                        fromVo.setNickName(friend.getRemark());
                    }
                }
            }

            bodyVo.setFromInfo(fromVo);

            PushToVo pushToVo = new PushToVo()
                    .setUserId(String.valueOf(group.getId()))
                    .setPortrait(group.getPortrait())
                    .setNickName(group.getName());
            bodyVo.setGroupInfo(pushToVo);

            pushBodyVos.add(bodyVo);
        }

        return pushBodyVos;
    }

}
